package com.property.demo.service.impl;

import com.property.demo.model.Community;
import com.property.demo.model.Parking;
import com.property.demo.repository.CommunityRepository;
import com.property.demo.repository.ParkingRepository;
import com.property.demo.service.ParkingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;

@Service
public class ParkingServiceImpl implements ParkingService {

    @Autowired
    private ParkingRepository parkingRepository;
    
    @Autowired
    private CommunityRepository communityRepository;

    @Override
    public List<Parking> findAll() {
        return parkingRepository.findAll();
    }

    @Override
    public Page<Parking> findAll(Pageable pageable) {
        return parkingRepository.findAll(pageable);
    }

    @Override
    public Page<Parking> findByFilters(Long communityId, String name, String status, Pageable pageable) {
        Specification<Parking> spec = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            
            if (communityId != null) {
                predicates.add(criteriaBuilder.equal(root.get("community").get("id"), communityId));
            }
            
            if (name != null && !name.isEmpty()) {
                predicates.add(criteriaBuilder.like(criteriaBuilder.lower(root.get("name")), "%" + name.toLowerCase() + "%"));
            }
            
            if (status != null && !status.isEmpty()) {
                predicates.add(criteriaBuilder.equal(root.get("status"), status));
            }
            
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
        
        return parkingRepository.findAll(spec, pageable);
    }

    @Override
    public Parking findById(Long id) {
        return parkingRepository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("Parking not found with id: " + id));
    }

    @Override
    public Parking save(Parking parking) {
        // Verify community exists
        Community community = communityRepository.findById(parking.getCommunity().getId())
                .orElseThrow(() -> new EntityNotFoundException("Community not found with id: " + parking.getCommunity().getId()));
        
        parking.setCommunity(community);
        return parkingRepository.save(parking);
    }

    @Override
    public Parking update(Long id, Parking parkingDetails) {
        Parking parking = findById(id);
        
        parking.setName(parkingDetails.getName());
        
        // Only update community if it's provided
        if (parkingDetails.getCommunity() != null && parkingDetails.getCommunity().getId() != null) {
            Community community = communityRepository.findById(parkingDetails.getCommunity().getId())
                    .orElseThrow(() -> new EntityNotFoundException("Community not found with id: " + parkingDetails.getCommunity().getId()));
            parking.setCommunity(community);
        }
        
        parking.setType(parkingDetails.getType());
        parking.setStatus(parkingDetails.getStatus());
        parking.setArea(parkingDetails.getArea());
        parking.setPrice(parkingDetails.getPrice());
        
        return parkingRepository.save(parking);
    }

    @Override
    public void delete(Long id) {
        Parking parking = findById(id);
        parkingRepository.delete(parking);
    }

    @Override
    public List<Parking> findByCommunityId(Long communityId) {
        // Verify community exists
        communityRepository.findById(communityId)
                .orElseThrow(() -> new EntityNotFoundException("Community not found with id: " + communityId));
                
        return parkingRepository.findByCommunityId(communityId);
    }

    @Override
    public List<Parking> findByNameContaining(String name) {
        return parkingRepository.findByNameContaining(name);
    }

    @Override
    public List<Parking> findByNameContainingAndCommunityId(String name, Long communityId) {
        // Verify community exists
        communityRepository.findById(communityId)
                .orElseThrow(() -> new EntityNotFoundException("Community not found with id: " + communityId));
                
        return parkingRepository.findByNameContainingAndCommunityId(name, communityId);
    }

    @Override
    public List<Parking> findByStatus(String status) {
        return parkingRepository.findByStatus(status);
    }
} 
